Grafanaでrechartsを使ってパネルプラグインを作ってみた
こんにちは。CX事業本部Delivery部のakkyです。
Grafanaはプラグインで機能を拡張することができ、さまざまなプラグインが公開されています。 パネル(フロントエンド)プラグインでは独自の可視化が可能になり、バックエンドプラグインでは独自のデータソースへの接続が可能になります。 フロンエンドの部分はReactで書き、バックエンドは基本的にはgo言語で書きます(gRPC対応であれば他の言語も対応)。
今回は、パネルプラグイン開発のチュートリアルを参考に、recharts(グラフライブラリ)を組み合わせて独自にグラフが表示できることを試してみました。
Amazon Managed Grafanaでは独自のプラグインをインストールすることはできません。
使用ソフトウェア
- Grafana 10.0.5
- Node.js 18.17.1
- @grafana/create-plugin 1.12.2
- recharts 2.8.0
Reactは17.0.2がインストールされました。
また、開発はWSL上のUbuntu22.04で行いました。
プラグインの開発
サンプルのビルド
Grafana公式のプラグイン作成チュートリアルを参考に行っていきます。
まずはテンプレートを作成します。適切な名前を付け、プラグインのタイプにpanelを選びます。
npx @grafana/create-plugin@latest ? What is going to be the name of your plugin? testpanel ? What is the organization name of your plugin? classmethod ? How would you describe your plugin? ? What type of plugin would you like? panel ? Do you want to add Github CI and Release workflows? No ? Do you want to add a Github workflow for automatically checking "Grafana API compatibility" on PRs? No
任意のパッケージマネージャー(今回はyarn)でモジュールを入れます。
cd classmethod-my-panel/ yarn install
次のコマンドでビルドします。
yarn run build
rechartsのインストールと開発
まずはrechartsを追加します。
yarn add recharts
プラグインを開発していきます。
パラメータの定義
まずは、パネルの設定に使うためのパラメータを定義していきます。今回は線の色だけ設定できるようにしてみました。
export interface SimpleOptions { linecolor: string }
設定画面の定義
ここの詳しいドキュメントがなかったのですが、addColorPicker
などのUIコンポーネントは@grafana/ui
で定義されているものです。
Colorpickerの説明はこちらです。UIコンポーネントにパラメーターを渡すには、settings
をつくって入れる必要がありました。
今回はenableNamedColors: true
として、色の名前がそのまま渡されるようにしています。色名からカラーコードへの変更はパネル本体のコードで書きます。
import { PanelPlugin } from '@grafana/data'; import { SimpleOptions } from './types'; import { SimplePanel } from './components/SimplePanel'; export const plugin = new PanelPlugin<SimpleOptions>(SimplePanel).setPanelOptions((builder) => { return builder .addColorPicker({ path: "linecolor", name: "Select line name", defaultValue: "#F00", settings: { enableNamedColors: true } }); });
次のような設定項目になります
パネル本体
Reactそのままで書くことができるので、主にrechatsの知識が必要になります。まずはシンプルな折れ線グラフを作ってみました。
Grafana特有の知識としては以下の点があります
- 設定値がoptions
に入ってくる
- 画面テーマやコンポーネントは@grafana/ui
を使う
- 表示するデータのフォーマット
データフォーマットはDataFrames形式で渡されますので、これを適宜加工して使います。
Grafanaでは、値と時刻がそれぞれの配列で渡されますが、rechatsでは値と時刻をセットにしたobjectの配列が必要なので、系列ごとのデータを分解して構成します。
設定画面で登場したカラーピッカーから渡される色名はtheme.visualization.getColorByName()
を使ってカラーコードに変換できました。
import React from 'react'; import { FieldType, PanelProps } from '@grafana/data'; import { SimpleOptions } from 'types'; import { useTheme2 } from '@grafana/ui'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; interface Props extends PanelProps<SimpleOptions> {} export const SimplePanel: React.FC<Props> = ({ options, data }) => { const frame = data.series[0]; const timeField = frame.fields.find((field) => field.type === FieldType.time); const valueField = frame.fields.find((field) => field.type === FieldType.number); const filed_name = valueField!.name; const formatted_data = []; for (const [index, value] of timeField!.values.entries()) { const date_str = new Date(value).toLocaleString("ja-JP"); formatted_data.push({ "time": date_str, [valueField!.name]: valueField!.values[index] }); } // Convert color name to color code const theme = useTheme2(); const colorcode = theme.visualization.getColorByName(options.linecolor); return ( <ResponsiveContainer width="100%" height="100%"> <LineChart data={formatted_data} margin={{ top: 5, right: 30, left: 20, bottom: 5, }}> <CartesianGrid strokeDasharray="3 3" /> <XAxis dataKey="time" /> <YAxis type='number' domain={['auto', 'auto']}/> <Tooltip contentStyle={{backgroundColor: theme.colors.background.primary}} itemStyle={{ color: colorcode }} /> <Legend /> <Line type="linear" dataKey={filed_name} stroke={colorcode} isAnimationActive={false} dot={false}/> </LineChart> </ResponsiveContainer> ); };
ビルドと実行
先ほどと同様にyarn run build
でビルドを行い、コンテナで動作テストします。
podman(dockerでも動くと思います)で実行します。GF_DEFAULT_APP_MODEを設定しないと、開発中で署名されていないプラグインを使うことができません。
podman run -d -p 3000:3000 -v ~/classmethod-test-panel:/var/lib/grafana/plugins -e GF_DEFAULT_APP_MODE=development --name=grafana docker.io/grafana/grafana:10.0.5
Grafanaを開き、今回作ったパネルを選択すると、ただしくグラフが表示できました!
なお、開発中にプラグインを更新しても、キャッシュが強く効くため、通常の更新ではうまくいきません。 Chromeの場合はSuper Reloaderを入れるとうまくいきました。
おわりに
Grafanaで独自のパネルプラグインを開発してみました。
Reactコンポーネントとして開発できるので、当初の想定より手軽に開発できました。 Grafanaを使うと、認証やDBからの接続をすべて任せてグラフの開発に集中できて便利ですね。